package com.wstuo.common.security.service;

import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.io.StringWriter;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.List;

import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;

import com.wstuo.common.dto.PageDTO;
import com.wstuo.common.exception.ApplicationException;
import com.wstuo.common.file.csv.CSVReader;
import com.wstuo.common.file.csv.CSVWriter;
import com.wstuo.common.security.dao.IFunctionDAO;
import com.wstuo.common.security.dao.IOperationDAO;
import com.wstuo.common.security.dao.IResourceDAO;
import com.wstuo.common.security.dto.FunctionDTO;
import com.wstuo.common.security.dto.FunctionQueryDTO;
import com.wstuo.common.security.dto.FunctionTreeDTO;
import com.wstuo.common.security.entity.Function;
import com.wstuo.common.security.entity.Operation;
import com.wstuo.common.security.utils.FileEncodeUtils;
import com.wstuo.common.security.utils.LanguageContent;
import com.wstuo.common.util.MathUtils;
import com.wstuo.common.util.StringUtils;

/**
 * 功能业务类
 */
@SuppressWarnings("unchecked")
public class FunctionService implements IFunctionService {
	private final static Logger LOGGER = Logger.getLogger(FunctionService.class);
	@Autowired
	private IFunctionDAO functionDAO;
	@Autowired
	private IOperationDAO operationDAO;
	@Autowired
	private IResourceDAO resourceDAO;

	/**
	 * 分页查询功能.
	 * 
	 * @param functionQueryDTO
	 *            分页查询DTO：FunctionQueryDTO
	 * @return 分页数据：PageDTO
	 */
	@Transactional
	public PageDTO findPagerFunction(FunctionQueryDTO functionQueryDTO) {
		PageDTO p = functionDAO.findPager(functionQueryDTO);
		List<Function> entities = (List<Function>) p.getData();
		List<FunctionDTO> dtos = new ArrayList<FunctionDTO>();

		for (Function entity : entities) {
			FunctionDTO dto = new FunctionDTO();

			if (entity.getParentFunction() != null) {
				dto.setParentFunctionName(entity.getParentFunction().getResName());
				dto.setParentFunctionNo(entity.getParentFunction().getResNo());
			}

			FunctionDTO.entity2dto(entity, dto);

			dtos.add(dto);
		}

		p.setData(dtos);

		return p;
	}

	/**
	 * 查找全部功能
	 * 
	 * @return 功能集合 List<FunctionDTO>
	 */
	public List<FunctionDTO> findAllFunction() {
		List<Function> entities = functionDAO.findAll();
		List<FunctionDTO> dtos = new ArrayList<FunctionDTO>(entities.size());

		for (Function entity : entities) {
			FunctionDTO dto = new FunctionDTO();

			FunctionDTO.entity2dto(entity, dto);
			dtos.add(dto);
		}

		return dtos;
	}

	/**
	 * 查找功能(树结构)
	 * 
	 * @return 树形集合：List<FunctionTreeDTO>
	 */
	@Transactional
	public List<FunctionTreeDTO> findFunctionTreeDtos(String resCode) {
		List<FunctionTreeDTO> dtos = new ArrayList<FunctionTreeDTO>();
		List<Function> entities = functionDAO.findRoots(resCode);

		for (Function func : entities) {

			if (func.getDataFlag() != 99) {
				FunctionTreeDTO dto = new FunctionTreeDTO();
				FunctionTreeDTO.entity2dto(func, dto);
				dtos.add(dto);
			}
		}

		return dtos;
	}

	/**
	 * 新增功能.
	 * 
	 * @param functionDto
	 *            功能DTO:FunctionDTO
	 */
	@Transactional()
	public void addFunction(FunctionDTO functionDto) {
		Function entity = new Function();

		FunctionDTO.dto2entity(functionDto, entity);

		if (functionDto.getParentFunctionNo() != null) {
			Function parentFunction = functionDAO.findById(functionDto.getParentFunctionNo());

			entity.setParentFunction(parentFunction);
		} else {
			if (functionDto.getParentFunctionResCode() != null) {
				Function parentFunction = functionDAO.findUniqueBy("resCode", functionDto.getParentFunctionResCode());
				entity.setParentFunction(parentFunction);
			}
		}

		functionDAO.save(entity);

		functionDto.setResNo(entity.getResNo());
	}

	/**
	 * 添加默认操作
	 * 
	 * @param functionDto
	 */
	@Transactional()
	public void addDefaultOperations(FunctionDTO functionDto) {
		Function entity = functionDAO.findById(functionDto.getResNo());
		String resUrl = functionDto.getResUrl();
		String resCode = functionDto.getResCode();

		if (resUrl != null) {
			if (resUrl.indexOf(".") != -1) {
				resUrl = resUrl.substring(0, resUrl.indexOf("."));
			}
		} else {
			resUrl = "";
		}

		if (resCode == null) {
			resCode = "";
		}
		LanguageContent lc = LanguageContent.getInstance();
		// 自动（增删查改）
		Operation add = new Operation();

		add.setFunction(entity);
		add.setResName(lc.getContent("common.add"));
		add.setResCode(resCode + "AD");
		add.setResUrl(resUrl + "!add.action");
		add.setResIcon("add.png");
		operationDAO.save(add);

		Operation delete = new Operation();

		delete.setFunction(entity);
		delete.setResName(lc.getContent("common.delete"));
		delete.setResCode(resCode + "DL");
		delete.setResUrl(resUrl + "!delete.action");
		delete.setResIcon("delete.png");
		operationDAO.save(delete);

		Operation find = new Operation();

		find.setFunction(entity);
		find.setResName(lc.getContent("common.search"));
		find.setResCode(resCode + "SL");
		find.setResUrl(resUrl + "!find.action");
		find.setResIcon("find.png");
		operationDAO.save(find);

		Operation edit = new Operation();

		edit.setFunction(entity);
		edit.setResName(lc.getContent("common.edit"));
		edit.setResCode(resCode + "ED");
		edit.setResUrl(resUrl + "!edit.action");
		edit.setResIcon("edit.png");
		operationDAO.save(edit);
	}

	/**
	 * 修改功能.
	 * 
	 * @param functionDto
	 *            功能DTO：FunctionDTO
	 */
	@Transactional()
	public void upadteFunction(FunctionDTO functionDto) {

		// 验证数据
		resourceDAO.findExists2(functionDto.getResName(), functionDto.getResCode(), functionDto.getResUrl(), functionDto.getResNo());

		Function entity = functionDAO.findById(functionDto.getResNo());

		// 手动转换
		if (functionDto.getResName() != null) {
			entity.setResName(functionDto.getResName());
		}

		if (functionDto.getResCode() != null) {
			entity.setResCode(functionDto.getResCode());
		}

		if (functionDto.getResIcon() != null) {
			entity.setResIcon(functionDto.getResIcon());
		}

		if (functionDto.getResUrl() != null) {
			entity.setResUrl(functionDto.getResUrl());
		}

		if (MathUtils.isLongEmpty(functionDto.getParentFunctionNo())) {

			Function parent = functionDAO.findById(functionDto.getParentFunctionNo());
			entity.setParentFunction(parent);

		}

		functionDAO.merge(entity);
	}

	/**
	 * 根据编号删除功能.
	 * 
	 * @param resNo
	 *            功能编号：Long resNo
	 * @return boolean 值为true时删除成功，否则失败
	 */
	@Transactional()
	public boolean deleteFunction(Long resNo) {
		Boolean result = true;
		Byte delete = 1;
		Function entity = functionDAO.findById(resNo);

		if (entity.getDataFlag().toString().equals(delete.toString())) {
			result = false;
		}
		if (result) {
			functionDAO.delete(entity);
		}

		return result;
	}

	/**
	 * 根据编号删除功能.
	 * 
	 * @param resNos
	 *            功能编号：Long resNos
	 * @return boolean 值为true时删除成功，否则失败
	 */
	@Transactional()
	public boolean deleteFunction(Long[] resNos) {
		Boolean result = true;
		Byte delete = 1;

		for (Long id : resNos) {
			Function function = functionDAO.findById(id);

			if (function.getDataFlag().toString().equals(delete.toString())) {
				result = false;
			}
		}

		if (result) {
			functionDAO.deleteByIds(resNos);
		}

		return result;
	}

	/**
	 * 拷贝功能.
	 * 
	 * @param resNo
	 *            当前功能ID：Long resNo
	 * @param parentFunctionNo
	 *            拷贝到的父节点编号：Long parentFunctionNo
	 * @return FunctionDTO
	 */
	@Transactional
	public FunctionDTO copyFunction(Long resNo, Long parentFunctionNo) {

		Function newFunction = new Function();

		Function sourceFunction = functionDAO.findById(resNo);
		Function parentFunction = functionDAO.findById(parentFunctionNo);

		newFunction.setResName(sourceFunction.getResName() + "_copy");
		newFunction.setResCode(sourceFunction.getResCode() + "_copy");
		newFunction.setResUrl(sourceFunction.getResUrl() + "_copy");

		newFunction.setParentFunction(parentFunction);

		functionDAO.save(newFunction);
		// add mars 20110602
		FunctionDTO dto = new FunctionDTO();
		if (newFunction != null) {
			FunctionDTO.entity2dto(newFunction, dto);
		}
		if (newFunction.getParentFunction() != null) {
			dto.setParentFunctionNo(newFunction.getParentFunction().getResNo());
			dto.setParentFunctionName(newFunction.getParentFunction().getResName());
		}
		return dto;
	}

	/**
	 * 剪切（更改父节点)
	 * 
	 * @param resNo
	 *            当前功能ID：Long resNo
	 * @param parentFunctionNo
	 *            拷贝到的父节点编号：Long parentFunctionNo
	 */
	@Transactional()
	public void cutFunction(Long resNo, Long parentFunctionNo) {
		Function sourceFunction = functionDAO.findById(resNo);

		if (parentFunctionNo == -1) {
			sourceFunction.setParentFunction(null);
		} else {
			Function parentFunction = functionDAO.findById(parentFunctionNo);

			sourceFunction.setParentFunction(parentFunction);
		}

		functionDAO.merge(sourceFunction);
	}

	/**
	 * 验证功能是否已经存在.
	 * 
	 * @param qdto
	 *            功能查询DTO:FunctionQueryDTO
	 * @return boolean true为存在，反之不存在
	 */
	public Boolean findFunctionExist(FunctionQueryDTO qdto) {
		return functionDAO.findExist(qdto);
	}

	/**
	 * 根据ID获取function
	 * 
	 * @param resNo
	 * @return FunctionDTO
	 */
	@Transactional
	public FunctionDTO findById(Long resNo) {
		FunctionDTO dto = new FunctionDTO();
		Function entity = functionDAO.findById(resNo);
		if (entity != null) {
			FunctionDTO.entity2dto(entity, dto);
		}
		if (entity != null && entity.getParentFunction() != null) {
			dto.setParentFunctionNo(entity.getParentFunction().getResNo());
			dto.setParentFunctionName(entity.getParentFunction().getResName());
		}
		return dto;
	}

	/**
	 * 导出CSV
	 * 
	 * @param qdto
	 * @return InputStream
	 */
	@Transactional
	public InputStream exportFunction(FunctionQueryDTO qdto) {

		LanguageContent lc = LanguageContent.getInstance();
		List<String[]> data = new ArrayList<String[]>();
		data.add(new String[] { lc.getContent("common.id"), lc.getContent("label.role.roleName"), lc.getContent("label.resource.functionCode"), lc.getContent("label.resource.functionUrl"), lc.getContent("label.resource.functionIcon"), lc.getContent("title.resource.parentFunction") });// 加入表头

		// 升序排列
		qdto.setSord("asc");
		qdto.setSidx("resNo");
		qdto.setStart(0);
		qdto.setLimit(1000);

		PageDTO p = functionDAO.findPager(qdto);
		List<Function> entities = (List<Function>) p.getData();
		String parentFunction = "";

		for (Function func : entities) {

			if (func.getParentFunction() != null) {
				parentFunction = func.getParentFunction().getResName();
			}
			data.add(new String[] { func.getResNo() + "", func.getResName(), func.getResCode() + "", func.getResUrl(), func.getResIcon(), parentFunction });
			parentFunction = "";
		}

		StringWriter sw = new StringWriter();
		CSVWriter csvw = new CSVWriter(sw);

		csvw.writeAll(data);
		byte[] bs = null;
		try {
			bs = sw.getBuffer().toString().getBytes("GBK");
		} catch (UnsupportedEncodingException e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		}
		
		ByteArrayInputStream stream = null;
		if(bs!=null){
			stream = new ByteArrayInputStream(bs);
		}
		try {
			if (csvw != null) {
				csvw.flush();
				csvw.close();
			}
			if (sw != null) {
				sw.flush();
				sw.close();
			}
		} catch (IOException e) {
			LOGGER.error(e);
		}
		return stream;
	}

	/**
	 * 导入CSV
	 * 
	 * @param filePath
	 * @return String
	 */
	@Transactional
	public String importFunction(String filePath) {
		try {
			String fileEncode = FileEncodeUtils.getFileEncode(new File(filePath));
			Reader rd = new InputStreamReader(new FileInputStream(filePath), fileEncode);// 以字节流方式读取数据
			CSVReader reader = new CSVReader(rd);
			String[] line = null;
			while ((line = reader.readNext()) != null) {
				Function func = new Function();
				func.setResNo(Long.parseLong(line[0].toString()));
				func.setResName(line[1].toString());
				func.setResCode(line[2].toString());
				func.setResUrl(line[3].toString());
				func.setResIcon(line[4].toString());
				if (StringUtils.hasText(line[5])) {// 关联父功能
					func.setParentFunction(getFunctionByFunctionNoStr(line[5]));
				}
				if (StringUtils.hasText(line[6]))
					func.setDataFlag((byte) Integer.parseInt(line[6]));
				functionDAO.save(func);
			}
			return "success";
		} catch (Exception ex) {

			throw new ApplicationException("ERROR_CSV_FILE_NOT_EXISTS\n" + ex, ex);
		}

	}

	/**
	 * 根据编号字符查找功能.
	 * 
	 * @param functionUrl
	 * @return Function
	 */
	@Transactional
	public Function getFunctionByFunctionNoStr(String functionUrl) {

		try {
			Function func = functionDAO.findUniqueBy("resUrl", functionUrl);
			if (func == null) {

				throw new ApplicationException("ERROR_NULL_PARENT_FUNCTION");

			} else {

				return func;
			}
		} catch (NumberFormatException ex) {

			throw new ApplicationException("ERROR_NUMBERFORMAT\n" + ex, ex);
		}
	}

}
